<template>
  <div class="app-container">
    <div class="operation-area">
      <a-row>
        <a-space>
          <a-button type="primary" @click="handleAdd">添加</a-button>
        </a-space>
      </a-row>
    </div>
    <div class="table-area">
      <a-table
        :columns="columns"
        :data="roleList"
        :loading="loading"
        :pagination="{
          total: total,
          current: queryParams.pageNum,
          pageSize: queryParams.pageSize,
          showJumper: true,
          showTotal: true,
          showPageSize: true,
          pageSizeOptions: [10, 20, 30, 50, 100, 200]
        }"
        @page-change="tablePageChange"
        @page-size-change="tablePageSizeChange"
      >
        <template #createTime="{ record }">
          <span>{{ parseTime(record.createTime) }}</span>
        </template>
        <template #updateTime="{ record }">
          <span>{{ parseTime(record.updateTime) }}</span>
        </template>
        <template #optional="{ record }">
          <a-space>
            <a-button type="text" @click="handlePermission(record)"
              >菜单权限</a-button
            >
            <a-button type="text" @click="handleUpdate(record)">编辑</a-button>
            <a-button type="text" status="danger" @click="handleDelete(record)"
              >删除</a-button
            >
          </a-space>
        </template>
      </a-table>
    </div>
    <a-modal v-model:visible="open" :title="title">
      <a-form ref="roleRef" :model="form" :rules="rules">
        <a-form-item label="角色名称" field="roleName">
          <a-input v-model="form.roleName" placeholder="请输入角色名称" />
        </a-form-item>
        <a-form-item label="备注" field="remark">
          <a-input v-model="form.remark" placeholder="" />
        </a-form-item>
      </a-form>
      <template #footer>
        <a-row justify="end">
          <a-space>
            <a-button @click="cancel">取消</a-button>
            <a-button type="primary" @click="submitForm" :loading="okLoading"
              >确定</a-button
            >
          </a-space>
        </a-row>
      </template>
    </a-modal>
    <a-modal
      v-model:visible="openPermission"
      :title="title"
      unmount-on-close
      :body-style="{ 'max-height': '80vh' }"
    >
      <div class="tree-bar">
        <a-tree
          :checkable="true"
          v-model:checked-keys="checkedKeys"
          v-model:half-checked-keys="halfCheckedKeys"
          :check-strictly="false"
          :data="sysTrees"
          default-expand-all
          blockNode
          :fieldNames="{
            key: 'id',
            title: 'label',
            children: 'children'
          }"
        />
      </div>
      <template #footer>
        <a-row justify="end">
          <a-space>
            <a-button @click="cancelPermission">取消</a-button>
            <a-button
              type="primary"
              @click="submitPermission"
              :loading="okLoading"
              >确定</a-button
            >
          </a-space>
        </a-row>
      </template>
    </a-modal>
  </div>
</template>

<script setup name="Role">
import {
  listRole,
  addRole,
  updateRole,
  delRole,
  roleMenuTreeselect,
  insertRoleMenu
} from '@/api/system/role'
import { Modal, Message } from '@arco-design/web-vue'

const { proxy } = getCurrentInstance()

const roleList = ref([])
const open = ref(false)
const loading = ref(true)

const total = ref(0)
const title = ref('')

const okLoading = ref(false)
const roleRef = ref(null)

const sysTrees = ref([])
const permissionForm = ref({})
const checkedKeys = ref([])
const halfCheckedKeys = ref([])
const openPermission = ref(false)

const columns = ref([
  {
    title: '角色名称',
    dataIndex: 'roleName'
  },
  {
    title: '备注',
    dataIndex: 'remark'
  },
  {
    title: '创建时间',
    slotName: 'createTime'
  },
  {
    title: '更新时间',
    slotName: 'updateTime'
  },
  {
    title: '最后操作人',
    dataIndex: 'updateName'
  },
  {
    title: '操作',
    slotName: 'optional',
    width: 200,
    align: 'center'
  }
])

const data = reactive({
  form: {},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    roleName: undefined,
    roleKey: undefined,
    status: undefined
  },
  rules: {
    roleName: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }]
  }
})

const { queryParams, form, rules } = toRefs(data)

/** 查询角色列表 */
function getList() {
  loading.value = true
  listRole(queryParams.value).then((response) => {
    roleList.value = response.rows
    total.value = response.total
    loading.value = false
  })
}
function tablePageChange(num) {
  queryParams.value.pageNum = num
  getList()
}

// 每页数据数量
function tablePageSizeChange(pageSize) {
  queryParams.value.pageSize = pageSize
  queryParams.value.pageNum = 1
  getList()
}

function handlePermission(row) {
  permissionForm.value = {
    role: row
  }
  roleMenuTreeselect(row.roleId).then((res) => {
    sysTrees.value = res.menus || []
    const result = findHalfCheckedNodes(res.menus, res.checkedKeys, 'id')
    checkedKeys.value = result.checkedKeys || []
    halfCheckedKeys.value = result.halfCheckedKeys || []
    // checkedKeys.value = res.checkedKeys || []
    openPermission.value = true

    title.value = `分配${row.roleName}的菜单权限`
  })
}

// 筛选半选数据和全选数据
function findHalfCheckedNodes(menus, checkedKeys, pk = 'id') {
  // 保存半选节点
  let halfCheckedKeys = []

  const checkedKeySet = new Set(checkedKeys)

  // 递归处理树，返回当前节点是否全选
  function traverse(node) {
    if (node.children && node.children.length > 0) {
      let allChildrenChecked = true
      let childCheckedCount = 0

      // 遍历子节点，递归检查每个子节点的状态
      for (const child of node.children) {
        const isChildChecked = traverse(child)

        if (isChildChecked) {
          childCheckedCount++
        } else {
          allChildrenChecked = false // 有子节点未选中或部分选中
        }
      }

      // 如果子节点全部选中，返回 true
      if (childCheckedCount === node.children.length) {
        return true
      } else if (
        childCheckedCount > 0 &&
        childCheckedCount < node.children.length
      ) {
        // 如果子节点部分选中，当前节点为半选
        halfCheckedKeys.push(node[pk])
        checkedKeys = checkedKeys.filter((item) => item !== node[pk])
        return false
      } else {
        // 子节点没有全选，则当前节点也为半选
        if (checkedKeySet.has(node[pk])) {
          halfCheckedKeys.push(node[pk])
          checkedKeys = checkedKeys.filter((item) => item !== node[pk])
        }

        return false
      }
    } else {
      // 当前节点为叶子节点，检查它是否在 checkedKeys 中
      return checkedKeySet.has(node[pk])
    }
  }

  // 开始遍历树，从根节点开始
  for (const node of menus) {
    traverse(node)
  }

  return { halfCheckedKeys, checkedKeys }
}
function cancelPermission() {
  openPermission.value = false
}

function submitPermission() {
  okLoading.value = true
  insertRoleMenu({
    roleId: permissionForm.value.role.roleId,
    menuIds: [...checkedKeys.value, ...halfCheckedKeys.value]
  })
    .then((res) => {
      Message.success('分配菜单权限成功')
      okLoading.value = false
      openPermission.value = false
    })
    .finally(() => {
      okLoading.value = false
    })
}

/** 删除按钮操作 */
function handleDelete(row) {
  Modal.warning({
    title: '确认删除',
    content: '您确认要删除吗?',
    hideCancel: false,
    onOk: () => {
      delRole(row.roleId).then((res) => {
        Message.success('删除成功')
        getList()
      })
    }
  })
}

/** 重置新增的表单以及其他数据  */
function reset() {
  form.value = {
    roleId: undefined,
    roleName: undefined,
    remark: undefined
  }
  proxy.resetForm('roleRef')
}

/** 添加角色 */
function handleAdd() {
  reset()
  open.value = true
  title.value = '添加角色'
}

/** 编辑角色 */
function handleUpdate(row) {
  reset()
  form.value = {
    roleId: row.roleId,
    roleName: row.roleName,
    remark: row.remark
  }
  open.value = true
  title.value = '编辑角色'
}

/** 提交按钮 */
function submitForm() {
  roleRef.value.validate((errors) => {
    if (!errors) {
      okLoading.value = true
      if (form.value.roleId != undefined) {
        updateRole(form.value)
          .then((response) => {
            Message.success('编辑成功')
            open.value = false
            getList()
          })
          .finally(() => {
            okLoading.value = false
          })
      } else {
        addRole(form.value)
          .then((response) => {
            Message.success('新增成功')
            open.value = false
            getList()
          })
          .finally(() => {
            okLoading.value = false
          })
      }
    }
  })
}

/** 取消按钮 */
function cancel() {
  open.value = false
  okLoading.value = false
  reset()
}

getList()
</script>
